/** !Tree structure handling macros

This module conatins some convenience macros for handling tree
structures.  If you define your type as <pre>
typedef struct YOURTYPE {
    ...
    MX_TREE(struct YOURTYPE);
    ...
} YOURTYPE; </pre>
Then you can use these macros to manipulate your type as a tree.
*/

#ifndef MX__DEDS_TREE_HEADER
#define MX__DEDS_TREE_HEADER

#include <assert.h>

#ifdef __cplusplus
extern "C" {
#endif

/** !Declare elements for a tree structure
This macro declares elements for a tree structure.  This
delcaration must be included in a struct with an appropriate type.  The
surrounding type can then be manupulated by the other mx_tree_* functions. */
#define MX_TREE(type) \
    type *mx__treeparent;   \
    type *mx__treefirst;    \
    type *mx__treelast;     \
    type *mx__treenext;     \
    type *mx__treeprev

/** !Insert a tree element into a parent. 
The inserted element is placed after the existing children of the parent.  An tree element
cannot be inserted into itself. */
#define MX_TREE_INSERT(o,p)                     \
    do {                                        \
        assert(o);                              \
        assert(!(o)->mx__treeparent);           \
        assert(p);                              \
        assert((o) != (p));                     \
        if ((o) && (p) && ((o) != (p))) {       \
            (o)->mx__treeparent = (p);          \
            if ((p)->mx__treelast)              \
                (p)->mx__treelast->mx__treenext = (o);\
            (o)->mx__treeprev = (p)->mx__treelast;    \
            (o)->mx__treenext = 0;              \
            (p)->mx__treelast = (o);            \
            if (!(p)->mx__treefirst)            \
                (p)->mx__treefirst = (o);       \
        }                                       \
    } while (0)

/** !Remove a tree element from a parent. */
#define MX_TREE_REMOVE(o)                             \
    do {                                              \
        if ((o) && ((o)->mx__treeparent)) {                 \
            assert(o->mx__treeparent->mx__treefirst);             \
            assert(o->mx__treeparent->mx__treelast);              \
            if ((o)->mx__treeparent->mx__treelast == (o))         \
                (o)->mx__treeparent->mx__treelast = (o)->mx__treeprev;  \
            if ((o)->mx__treeparent->mx__treefirst == (o))        \
                (o)->mx__treeparent->mx__treefirst = (o)->mx__treenext; \
            if ((o)->mx__treeprev)                          \
                (o)->mx__treeprev->mx__treenext = (o)->mx__treenext;    \
            if ((o)->mx__treenext)                          \
                (o)->mx__treenext->mx__treeprev = (o)->mx__treeprev;    \
            (o)->mx__treenext = 0;                          \
            (o)->mx__treeprev = 0;                          \
            (o)->mx__treeparent = 0;                        \
        }                                             \
    } while (0)

/** !The first child element of a parent. */
#define mx_tree_first(o)   ((o)->mx__treefirst)

/** !The last child element of a parent. */
#define mx_tree_last(o)   ((o)->mx__treelast)

/** !The next child element with the same parent. */
#define mx_tree_next(o)   ((o)->mx__treenext)

/** !The previous child element with the same parent. */
#define mx_tree_prev(o)   ((o)->mx__treeprev)

/** !The parent tree element. */
#define mx_tree_parent(o) ((o)->mx__treeparent)

#ifdef __cplusplus
}
#endif
#endif
/*
    DEDS
    Data structures and utility functions for C
    Copyright (C) 2006 Douglas Eleveld

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
